/*! \file Server.c
    \brief Programa server. Establece comunicacion con un proceso cliente.
		Ejecuta los comandos recibidos, recibe archivos del mismo 
			y envia los archivos solicitados.
    
    Detalles.
*/
#include "error_parsing.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h> 
#include <unistd.h>
#include <sys/wait.h>
#include <stddef.h>
#include <errno.h>

#define BUFFSIZE 256
#define MAX 4000
#define TAMANIO 65000

/*! \fn void mensaje_error(int err, int* d)
    \brief Envia el mensaje de error correspondiente al valor almacenado en la variable errno
    \param err Almacena el valor de la variable \a errno, correpondiente al ultimo error ocurrido
		en la ejecucion del programa
	\param *d Puntero al \a file \a descriptor correspondiente al socket cliente TCP
*/
void mensaje_error(int err, int* d);

/*! \fn int Crear_Servidor_TCP();
    \brief Crea un socket servidor de la familia INET, que hace uso del protocolo TCP, y establece la
		conexion con el cliente
    \return El \a file \a descriptor del socket cliente que se ha conectado
*/
int Crear_Servidor_TCP();

/*! \fn int Crear_Servidor_UDP(struct sockaddr_in *st_servidor)
    \brief Crea un socket cliente de la familia INET, que hace uso del protocolo UDP
    \param *serv_addr Puntero a la estructura que almacenara los datos del \a servidor
    \return El \a file \a descriptor del socket servidor UDP creado
*/
int Crear_Servidor_UDP(struct sockaddr_in *st_servidor);

/*! \fn int Identificar_Comando(char *comando[ARGUMENTOS], char *buffer, int *fd_udp, struct sockaddr_in *s_UDP)
    \brief Identifica el comando ingresado y elige la accion que corresponde para cada caso
    \param *comando[ARGUMENTOS] En arreglo que contiene el comando a ejecutar y sus argumentos
    \param *buffer Almacena el resultado de la ejecucion del comando, si se realiza con exito
    \param *fd_udp Puntero al \a file \a descriptor del socket cliente UDP
    \param *s_UDP Puntero a la estructura que almacena los valores de los distintos campos del socket servidor UDP
    \return Un valor que puede ser \a cero en caso de exito, \a mayor \a a \a cero si ha ocurrido un error
		y \a menor \a a \a cero si se debe salir del programa
*/
int Identificar_Comando(char *comando[ARGUMENTOS], char *buffer, int *fd_udp, struct sockaddr_in *s_UDP);

/*! \fn int Realizar_cd(char *comandos[ARGUMENTOS], char *buffer)
    \brief Realiza el cambio de directorio
	\param *comandos[ARGUMENTOS] Contiene el comando y el directorio al que debe acceder
	\param *buffer Almacena un mensaje en caso de exito
    \return Un valor que puede ser \a cero en caso de exito o \a mayor \a a \a cero
		en caso de error
*/
int Realizar_cd(char *comandos[ARGUMENTOS], char *buffer);

/*! \fn int Ejecutar_ls_pwd(char* comandos[ARGUMENTOS], char *buffer)
    \brief Ejecuta el comando ingresado
	\param *comandos[ARGUMENTOS] Contiene el comando y los argumentos que puede aceptar el mismo
	\param *buffer Almacena el resultado de la ejecucion del comando
    \return Un valor que puede ser \a cero en caso de exito o \a mayor \a a \a cero
		en caso de error
*/
int Ejecutar_ls_pwd(char* comandos[ARGUMENTOS], char *buffer);

/*! \fn int Enviar_Archivo(char *comando[ARGUMENTOS],int *fd_UDP, char *buffer, struct sockaddr_in *s_UDP)
    \brief Envia un archivo al directorio en que se encuentra el \a cliente 
		haciendo uso de socket UDP, en respuesta al comando \a get
	\param *comando[ARGUMENTOS] Contiene el comando y el nombre del archivo a enviar
	\param *fd_UDP Referencia al file descriptor del socket cliente UDP
    \param *buffer Almacena un mensaje en caso de exito
    \param *s_UDP Puntero a la estructura que almacena los valores de los distintos campos del socket servidor UDP
    \return Un valor que puede ser \a cero en caso de exito o \a mayor \a a \a cero
		en caso de error
*/
int Enviar_Archivo(char *comando[ARGUMENTOS],int *fd_UDP, char *buffer, struct sockaddr_in *s_UDP);

/*! \fn int Recibir_Archivo(char *comando[ARGUMENTOS],int *fd_UDP, char *buffer, struct sockaddr_in *s_UDP)
    \brief Recibe un archivo desde la terminal donde se ejecuta el \a Cliente 
		haciendo uso de socket UDP, en respuesta al comando \a put
	\param *comando[ARGUMENTOS] Contiene el comando y el nombre del archivo a transmitir
	\param *fd_UDP Referencia al file descriptor del socket cliente UDP
    \param *buffer Almacena un mensaje en caso de exito
    \param *s_UDP Puntero a la estructura que almacena los valores de los distintos campos del socket servidor UDP
    \return Un valor que puede ser \a cero en caso de exito o \a mayor \a a \a cero
		en caso de error
*/
int Recibir_Archivo(char *comando[ARGUMENTOS],int *fd_UDP, char *buffer, struct sockaddr_in *s_UDP);

/*! \fn void Recibir_Comando(int *d_TCP, char *buffer)
    \brief Realiza la recepcion de comandos, caracter por caracter
    \param *d_TCP Puntero al \a file \a descriptor del socket cliente TCP
    \param *buffer Almacena el comando ingresado
*/
void Recibir_Comando(int *d_TCP, char *buffer);

/**
 * En la funcion \a main() se realiza la llamada a las funciones de creacion de los 
 * sockets que van a establecer la comunicacion con el proceso \a Cliente
 * y la llamada a las demas funciones que implica la ejecucion de los comandos.
 * Toma decisiones de acuerdo al resultado devuelto por cada comando ejecutado.
 * */
int main(int argc, char *argv[])
{
		int descriptor_UDP, descriptor_Cliente;
		struct sockaddr_in serv_addr;		// Estructura para crear servidor UDP
	
		/* Se realizan las llamadas a las funciones de creacion de socket*/
		descriptor_Cliente = Crear_Servidor_TCP();
		descriptor_UDP = Crear_Servidor_UDP(&serv_addr);
		
		char buffer[BUFFSIZE], contenido[MAX];
		char *comando[ARGUMENTOS];
		int n, argumentos;
		int res_operacion=0; 		// Variable que indica el resultado de la operacion ejecutada
			
		while(res_operacion >= 0)
		{
			bzero(buffer,BUFFSIZE);
			bzero(contenido, MAX);
			
			/* Se recibe comando */
			while(strlen(buffer)==0)
				Recibir_Comando(&descriptor_Cliente, buffer);
		
			/*	Se limpian los arreglos */
			for(n=0; n<ARGUMENTOS; n++) 
				comando[n]=NULL;
			
			Parsing(buffer, comando, &argumentos);
			
			res_operacion = Identificar_Comando(comando,contenido, &descriptor_UDP, &serv_addr);
			
			/*---------------------------------------------------------- 
			 * 				Escribir en socket cliente TCP
			 *--------------------------------------------------------*/
			if(res_operacion == 0)
			{ 
				n = write(descriptor_Cliente,contenido,strlen(contenido));
				if (n < 0) error("ERROR writing to socket");
			}
			if(res_operacion > 0)
			{
				mensaje_error(res_operacion, &descriptor_Cliente);
			}
			if (res_operacion ==-1)
			{
				n = write(descriptor_Cliente,contenido,strlen(contenido));
				if (n < 0) error("ERROR writing to socket");
			}
		}

	close(descriptor_UDP);
	close(descriptor_Cliente);
	
	return 0;
}


/*--------------------------------------------------------------------------------
 * 				Realiza el manejo de los mensajes de error
 * ------------------------------------------------------------------------------*/
void mensaje_error(int err, int* d)
{
	char mens_err[BUFFSIZE];
	bzero(mens_err, BUFFSIZE);
	strncpy(mens_err, "ERROR : ", 8);
	strncat(mens_err, strerror(err), strlen(strerror(err)));
	strcat(mens_err, "\n");
	
	if((write((*d),mens_err,strlen(mens_err))) < 0)
		error("ERROR writing to socket");	
}

/*--------------------------------------------------------------------------------
 * 							Crea un socket servidor TCP
 * ------------------------------------------------------------------------------*/
int Crear_Servidor_TCP()
{
	int descriptor_TCP;
	struct sockaddr_in st_servidor;		// Estructura para almacenar datos de servidor TCP
	struct sockaddr_in st_cliente;		// Estructura para almacenar valores de cliente
	
	/* Se abre el socket */
	descriptor_TCP = socket(AF_INET, SOCK_STREAM, 0);
    if (descriptor_TCP < 0) 
        error("ERROR opening socket");
	
	/* Limpieza de la estructura */
	memset(&st_servidor, 0, sizeof( st_servidor ) );
	/* Carga de la familia de direccioens */
	st_servidor.sin_family = AF_INET;
	/* Carga del número de puerto */
	st_servidor.sin_port = htons(6211);
	/* Carga de dirección IPv4 del socket, asumiendo que
	fue pasado como primer argumento al programa */
	st_servidor.sin_addr.s_addr =htonl(INADDR_ANY);
	/* Se rellena el campo con ceros */
	bzero ( &(st_servidor.sin_zero), 8);
 
	/*	Ligar una direccion al socket */
	int resultado;
	resultado = bind( descriptor_TCP,(struct sockaddr *) &st_servidor, (socklen_t) sizeof( st_servidor ));
	if (resultado< 0)
		error( "bind" );
	
	/*	Espera solicitud de conexion de clientes  */
	if (listen (descriptor_TCP, 1) == -1) 	
		error("Error"); 
		
	/*	Acepta solicitudes de conexion  */
	int descriptor_Cliente; 
	socklen_t longitud_Cliente; 

	longitud_Cliente = sizeof(st_cliente);
     
	descriptor_Cliente = accept (descriptor_TCP, (struct sockaddr *) &st_cliente, &longitud_Cliente); 
	if (descriptor_Cliente == -1) 
	{ 
		error ("Error al aceptar cliente"); 
	}
	close(descriptor_TCP);
	return descriptor_Cliente;
}

/*--------------------------------------------------------------------------------
 * 								Crea servidor UDP
 * ------------------------------------------------------------------------------*/
int Crear_Servidor_UDP(struct sockaddr_in *st_servidor)
{
	int descriptor;

	/* Se abre el socket */
	descriptor = socket (AF_INET, SOCK_DGRAM, 0);
	if (descriptor < 0) 
        error("ERROR opening socket");
	
	/* Limpieza de la estructura */
	memset(&(*st_servidor), 0, sizeof( *st_servidor ) );
	/* Carga de la familia de direcciones */
	st_servidor -> sin_family = AF_INET;
	/* Carga del número de puerto */
	st_servidor->sin_port = htons(6210);
	/* Carga de dirección IPv4 del socket, asumiendo que
	fue pasado como primer argumento al programa */
	st_servidor->sin_addr.s_addr =htonl(INADDR_ANY);	
	/* Relleno con ceros*/
	bzero ( &(st_servidor->sin_zero), 8);
 
	int resultado;
	
	/* Se asocia el socket con una direccion */
	resultado = bind( descriptor,(struct sockaddr *) &(*st_servidor), sizeof( *st_servidor ));
	if (resultado< 0){
		error( "bind" );
	}
	return descriptor;		
}

/*--------------------------------------------------------------------------------
 * 			Identifica el comando ingresado y realiza la llamada a la 
 * 					funcion correspondiente para su ejecucion
 * ------------------------------------------------------------------------------*/
int Identificar_Comando(char *comando[ARGUMENTOS], char *buffer, int *fd_udp, struct sockaddr_in *s_UDP)
{
	
	int success = 0;	// Almacena el valor dependiendo del resultado de la ejecucion del comando

	if(((strcmp("get",comando[0]))==0) && (comando[1]!= NULL))
	{
		return success = Enviar_Archivo(comando, &(*fd_udp), buffer, &(*s_UDP));
	} 
	if(((strcmp("put",comando[0]))==0) && (comando[1]!= NULL))
	{
		return success = Recibir_Archivo(comando, &(*fd_udp), buffer, &(*s_UDP));
	}
	if((strcmp("cd",comando[0]))==0)
	{
		return success = Realizar_cd(comando,buffer);
	}
	if(((strcmp("bye",comando[0]))==0) && (comando[1]== NULL))
	{
		strncpy(buffer,"Fin de la comunicacion\n",23);
		return -1;
	}
	return success = Ejecutar_ls_pwd(comando, buffer);
}

/*--------------------------------------------------------------------------------
 * 							Ejecuta los comandos 
 * ------------------------------------------------------------------------------*/
int Ejecutar_ls_pwd(char* comandos[ARGUMENTOS], char *buffer)
{
		int pipefd[2];
		int success =0;
		bzero (buffer, MAX);
		pipe(pipefd);

		if (fork() == 0)
		{	// Proceso hijo
			
			/* El proceso hijo cierra el extremo de lectura */
			close(pipefd[0]); 
			/* Envia la stdout al pipe */   
			dup2(pipefd[1], 1);  
			/* Envia el stderr al pipe */
			dup2(pipefd[1], 2);  
			/* Se cierra este descriptor porque ya no se necesita */
			close(pipefd[1]);  
			
			/* Ejecuta un comando, si ocurre un error, envia el valor de 'errno' al pipe*/
			if(execvp(comandos[0], comandos) < 0)
				printf("errno %i\n", errno);
			_exit(-1);			
		}
		else
		{	// Proceso padre
		
			bzero(buffer,MAX);
			close(pipefd[1]);  // Se cierra el extremo de escritura en el proceso padre
			
			/* Se lee del extremo del pipe, la entrada generada por el proceso hijo*/
			while (read(pipefd[0], buffer, MAX) != 0);			
			/* Se reconoce si hubo un error en la ejecucion y recupera el valor de la variable 'errno'*/
			if (!strncmp(buffer,"errno",5))
				success = atoi(buffer+6);
		}	
		return success;
}

/*--------------------------------------------------------------------------------
 * 						Realiza el cambio de directorio
 * ------------------------------------------------------------------------------*/
int Realizar_cd(char *comandos[ARGUMENTOS], char *buffer)
{		
	if(chdir(comandos[1]) < 0)
		return errno;
	strncpy(buffer,"Directorio actualizado\n",23);
	return 0;
}

/*--------------------------------------------------------------------------------
 * 							  Ejecuta comando 'get'
 * ------------------------------------------------------------------------------*/
int Enviar_Archivo(char *comando[ARGUMENTOS],int *fd_UDP, char *buffer, struct sockaddr_in *s_UDP)
{
		FILE *fich;
		char nombre_archivo[BUFFSIZE];
		int tamanio;
		char buff_tamanio[BUFFSIZE];	// Buffer auxiliar
		
		bzero(nombre_archivo, BUFFSIZE);	
		bzero(buff_tamanio, BUFFSIZE);
		
		/* Almacena nombre del archivo en arreglo */
		strncpy(nombre_archivo, comando[1], strlen(comando[1]));
	
	/*------------------------------------------------------------------
	 * 			Apertura de archivo para lectura en modo binario.
	 * 			En caso de fallo, se comunica al proceso cliente
	 *----------------------------------------------------------------*/
		fich = fopen(nombre_archivo,"rb");
		if(!fich)
		{
			socklen_t tamanio_direc;
			tamanio_direc = sizeof(*s_UDP);
			int valor_error = errno;
			
			if(recvfrom( (*fd_UDP), buff_tamanio, 15, 0, (struct sockaddr *)&(*s_UDP),  &tamanio_direc)==-1)
			{
				error( "lectura de socket" );
			}

			if(sendto ((*fd_UDP), "error al abrir el archivo", 25, 0, (struct sockaddr *) &(*s_UDP), tamanio_direc)==-1)
			{
				error("error al enviar");
			}	
			return valor_error;	
		}
	
	/*------------------------------------------------------------------
	 * 					Se determina tamaño del archivo
	 *----------------------------------------------------------------*/
		fseek(fich, 0L, SEEK_END);
		tamanio = (int)ftell(fich);
		
		char buff_archivo[TAMANIO];		// Almacena todos los datos del archivo leido
		
		/* Coloca el indicador de posicion de fichero al inicio*/
		fseek( fich, 0L, SEEK_SET );
		
		bzero(buff_archivo, TAMANIO);
		bzero(buff_tamanio,BUFFSIZE);
		
		socklen_t tamanio_direc;
		tamanio_direc = sizeof(*s_UDP);
				
	/* ----------------------------------------------------------------------
	 * 				Se espera "listo" - Se envia tamaño del archivo 
	 * ---------------------------------------------------------------------*/ 
		if(recvfrom( (*fd_UDP), buff_tamanio, 15, 0, (struct sockaddr *)&(*s_UDP),  &tamanio_direc)==-1)
		{
			error( "lectura de socket" );
		}
		
		bzero(buff_tamanio,BUFFSIZE);
		
		sprintf(buff_tamanio, "%d", tamanio);
		if(sendto ((*fd_UDP), buff_tamanio, strlen(buff_tamanio), 0, (struct sockaddr *) &(*s_UDP), tamanio_direc)==-1)
		{
			error("error al enviar");
		}	
		
		bzero(buff_tamanio, BUFFSIZE);
		
	/*----------------------------------------------------------------------
	 *				Se espera "listo" - Se envia el archivo
	 *---------------------------------------------------------------------*/
		
			if(recvfrom( (*fd_UDP), buff_tamanio, 14, 0, (struct sockaddr *)&(*s_UDP),  &tamanio_direc)==-1)
			{
				error( "lectura de socket" );
			}
		
			int cant_paquetes,i, resto;
			
			/* Se calcula la cantidad de paquetes a transmitir */
			cant_paquetes = (tamanio/TAMANIO)+1;
			/* Se inicializa la variable 'resto' */
			resto = tamanio;
			
			for(i=0; i<cant_paquetes; i++)
			{
				bzero(buff_archivo,TAMANIO);
				/* Se envia el ultimo paquete al cliente*/
				if(resto<TAMANIO)
				{
					fread(buff_archivo,1,resto, fich);
					if(sendto ((*fd_UDP), buff_archivo, resto,0, (struct sockaddr *)&(*s_UDP),  tamanio_direc)==-1)
					{
						error("ERROR: no se pudo enviar archivo");
					}			
					bzero(buff_tamanio,BUFFSIZE);
					/* Se recibe confirmacion */
					if(recvfrom( (*fd_UDP), buff_tamanio, 6, 0, (struct sockaddr *)&(*s_UDP),  &tamanio_direc)==-1)
					{
						error( "lectura de socket" );
					}
				}
				else
				{
					/* Se envia un paquete de tamaño TAMANIO al cliente */
					fread(buff_archivo,1,TAMANIO, fich);
					if(sendto ((*fd_UDP), buff_archivo, TAMANIO, 0, (struct sockaddr *)&(*s_UDP),  tamanio_direc)==-1)
					{
						error("envio archivo");
					}			
					bzero(buff_tamanio,BUFFSIZE);
					/* Se recibe confirmacion */
					if(recvfrom( (*fd_UDP), buff_tamanio, 6, 0, (struct sockaddr *)&(*s_UDP),  &tamanio_direc)==-1)
					{
						error( "lectura de socket" );
					}
					/* Se actualiza la variable 'resto' */
					resto = resto - TAMANIO;
				}
			}
			
		strncpy(buffer,"Se transmitio el archivo\n",25);
		fclose(fich);
		return 0;
}

/*--------------------------------------------------------------------------------
 * 							  Ejecuta comando 'put'
 * ------------------------------------------------------------------------------*/
int Recibir_Archivo(char *comando[ARGUMENTOS],int *fd_UDP, char *buffer, struct sockaddr_in *s_UDP)
{
 
	socklen_t tamano_direccion;
	char buffer_aux[BUFFSIZE];
	int tamanio_archivo;
		
	bzero( buffer_aux, BUFFSIZE );
	tamano_direccion = sizeof( struct sockaddr );
	
	/*----------------------------------------------------------------
	 * 				Se lee tamaño de archivo a recibir
	 * --------------------------------------------------------------*/
		if(recvfrom((*fd_UDP), buffer_aux, BUFFSIZE, 0, (struct sockaddr *)&(*s_UDP),  &tamano_direccion)==-1)
		{
			error( "lectura de socket" );
		}
	
		/* Se averigua si cliente pudo abrir el archivo para transmitir.
		 * Si ocurrio algun error al abrir el archivo, se recibe el 
		 * 			codigo de error y transmite mensaje				  */
		if(!strncmp(buffer_aux,"error ",6))
		{
			int cod;
			cod = atoi(strrchr(buffer_aux, ' '));
			return cod;
		}
	
		tamanio_archivo = atoi(buffer_aux);
		
	/*----------------------------------------------------------------
	 * 			Se abre archivo para escritura en modo binario
	 * --------------------------------------------------------------*/
		FILE *fich;
		char nombre_archivo[BUFFSIZE];
	
		bzero(nombre_archivo, BUFFSIZE);
		
		strncat(nombre_archivo, "copia_", 6);
		if(strrchr(comando[1], '/'))
			strcat(nombre_archivo, strrchr(comando[1], '/')+1);
		else strcat(nombre_archivo, comando[1]);
		
		fich = fopen(nombre_archivo,"wb");
		{
			if(!fich)
			{
				return errno;
			}
		}
	
		char buffer_archivo[TAMANIO];
		bzero(buffer_archivo,TAMANIO);
		if(sendto ((*fd_UDP), "Tamanio de archivo recibido", 27, 0, (struct sockaddr *) &(*s_UDP), tamano_direccion )==-1)
		{
			error("ERROR: no se pudo enviar archivo\n");
		}
	
	/*------------------------------------------------------------------
	 * 						Recepcion de datos 
	 * ----------------------------------------------------------------*/
			int cant_paquetes,i, resto;
			
			/* Se calcula la cantidad de paquetes a recibir*/
			cant_paquetes = (tamanio_archivo/TAMANIO)+1;
			/* Se inicializa la variable 'resto'*/
			resto = tamanio_archivo;
			
			for(i=0; i<cant_paquetes; i++)
			{
				bzero(buffer_archivo,TAMANIO);
	
				if(resto<TAMANIO)
				{
					/*	Se lee del socket el ultimo paquete */
					if(recvfrom( (*fd_UDP), buffer_archivo, resto, 0, (struct sockaddr *)&(*s_UDP),  &tamano_direccion)==-1)
					{
						error( "lectura de socket" );
					}
					
					/*	Escribir en el archivo los datos obtenidos */
					fwrite(buffer_archivo,1,resto,fich);
					/* Se envia confirmacion */
					if(sendto ((*fd_UDP), "Recibi archivo", 14, 0, (struct sockaddr *) &(*s_UDP), tamano_direccion )==-1)
					{
						error("ERROR: no se pudo enviar archivo");
					}			
				}
				else
				{
					/*	Se lee del socket un paquete de datos de tamaño TAMANIO */
					if(recvfrom( (*fd_UDP), buffer_archivo, TAMANIO,  0, (struct sockaddr *)&(*s_UDP),  &tamano_direccion)==-1)
					{
						error( "lectura de socket" );
					}
					
					/*	Escribir en el archivo los datos obtenidos */
					fwrite(buffer_archivo,1,TAMANIO,fich);
					/* Se envia confirmacion */
					if(sendto ((*fd_UDP), "Recibi datos", 12, 0, (struct sockaddr *) &(*s_UDP), tamano_direccion )==-1)
					{
						error("ERROR: no se pudo enviar archivo");
					}
					/*  Actualizar la variable 'resto' */
					resto = resto - TAMANIO;
				}	
			}

	fclose(fich);
	strncpy(buffer, "Se transmitio el archivo\n",25);
	return 0;
}

/*-------------------------------------------------------------------------------
 * 				Se recibe el comando caracter por caracter
 *------------------------------------------------------------------------------*/
void Recibir_Comando(int *d_TCP, char *buffer)
{
	int terminar = 0, i=0;
	char caracter[BUFFSIZE];		// Almacena el caracter ingresado
	bzero( caracter, BUFFSIZE );
	
	printf("Comando ingresado: ");
	setvbuf(stdout, NULL, _IONBF, 0);
	
	do
	{ 
		bzero( caracter, BUFFSIZE );
		
		/* Se recibe caracter */
		if(read( *d_TCP, caracter, BUFFSIZE ) < 0)
		{
			error( "Lectura de socket" );
		}
		
		/* Si se ha presionado la tecla 'backspace' se debe eliminar el ultimo caracter */
		if(*caracter == 127)
		{
				/* Si no hay caracteres ingresados, no se debe hacer nada*/
				if(i>0){
					buffer[strlen(buffer)-1] = '\0';   
					printf("\b \b");
					i--;
				}
		}else if(*caracter == '\n'){ 
				/*	Si se ha presionado 'enter' terminar el ingreso del comando */
				terminar =1;
		}else {
			/*	Almacenar caracter en un arreglo */
			setvbuf(stdout, NULL, _IONBF, 0);
			buffer[i]= *caracter;
			printf("%s",caracter);
			i++;
		}
	
		if(write( *d_TCP, "UNIX : Obtuve su mensaje", 24 ) < 0)
		{
			error( "Escritura en socket" );
		}
	}while(terminar == 0);
	printf("\n");
}
